# _*_coding:utf-8_*_
"""
    Base prober driver define. All other prober driver should inherit from this class.
    Developed by Ivy.Li 2013.03.27.
   (C)Copyright 2013 Hech. All rights reserved
"""

#######NOTE for define Prover driver operation return value########
# if prober error can be ignored, please define return value in [20001,22000]
# if prober fatal error occured, please define return value in [25001,26000]
# Prober operation type define for semiconductor field
import os
import sys
import time
from ATS.util import constant

workpath = os.path.dirname(os.path.realpath(sys.argv[0]))
sys.path.insert(0, os.path.dirname(workpath))
from ATS.communication import pyvisaImpl

PR_INIT = 500
PR_MOVE = 501
PR_RELMOVE = 502
PR_RELRETURN = 503
PR_CHUCK = 504
PR_LOAD = 505
PR_UNLOAD = 506
PR_INK = 507

# define prober related fail error
PrInitFail = 21803
PrMoveFail = 21804
PrChuckFail = 21805
PrInkFail = 21806

# Prober type define
FAKE_PROBER = 0
HECH_PROBER = 1

NO_ERR = 0

PROBER_OBJ = None  ## For ATS, there is only one prober connection object.

VISA_OBJ = None  ## communication visa object, there is only 1 connection object for 1 prober.

##use prober type
PROBER_TYPE = FAKE_PROBER  # default as FAKE prober
PROBER_ADDR = 5
GPIB_CARDNUM = 'GPIB1'


def set_prb_info(info_dict):
    """
    PROBER_TYPE: FAKE or HECH is supported now. 2013/11/30
    info_dict{
    model: HECH or FAKE
    prober_addr: prober address
    }
    """
    global PROBER_TYPE
    global PROBER_ADDR
    global GPIB_CARDNUM

    model = info_dict.get('model', 'FAKE')
    if model == 'FAKE':
        PROBER_TYPE = FAKE_PROBER
    elif model == 'HECH':
        PROBER_TYPE = HECH_PROBER
    else:
        PROBER_TYPE = FAKE_PROBER

    addr = info_dict.get('prober_addr', '')

    if addr:
        PROBER_ADDR = addr

    card_num = info_dict.get('GPIB_CARDNUM'.lower(), '0')
    global GPIB_CARDNUM
    GPIB_CARDNUM = "GPIB%s" % card_num
    if not constant.build:
        print('PROBER_TYPE,PROBER_ADDR,GPIB_CARDNUM=', PROBER_TYPE, PROBER_ADDR, GPIB_CARDNUM)


def ProberFactory():
    global PROBER_OBJ
    global PROBER_TYPE

    if PROBER_OBJ is not None:
        return PROBER_OBJ

    if PROBER_TYPE == FAKE_PROBER:
        PROBER_OBJ = BaseProber()
    elif PROBER_TYPE == HECH_PROBER:
        PROBER_OBJ = WangProber()
    ##TO add branch here for different prober
    return PROBER_OBJ


class BaseProber:
    def __init__(self, type=FAKE_PROBER):
        self.type = type

    def dispatch_fun(self, Prb_opt, *args):
        if Prb_opt == PR_INIT:
            return self.PrInit(*args)
        elif Prb_opt == PR_MOVE:
            return self.PrMove(*args)
        elif Prb_opt == PR_RELMOVE:
            return self.PrRelMove(*args)
        elif Prb_opt == PR_RELRETURN:
            return self.PrRelReturn(*args)
        elif Prb_opt == PR_CHUCK:
            return self.PrChuck(*args)
        elif Prb_opt == PR_LOAD:
            return self.PrLoad(*args)
        elif Prb_opt == PR_UNLOAD:
            return self.PrUnload(*args)

    def PrInit(self, *args):
        if not constant.build:
            print('Fake PrInit:%s' % str(args))
        return NO_ERR

    def PrMove(self, *args):
        if not constant.build:
            print('Fake PrMove:%s' % str(args))
        return NO_ERR

    def PrRelMove(self, *args):
        if not constant.build:
            print('Fake PrRelMove:%s' % str(args))
        return NO_ERR

    def PrRelReturn(self, *args):
        if not constant.build:
            print('Fake PrRelReturn')
        return NO_ERR

    def PrChuck(self, *args):
        if not constant.build:
            print('Fake PrChuck:%s' % str(args))
        return NO_ERR

    def PrLoad(self, *args):
        if not constant.build:
            print('Fake PrLoad')
        return NO_ERR

    def PrUnload(self, *args):
        if not constant.build:
            print('Fake PrUnload')
        return NO_ERR

    def PrInk(self, *args):
        if not constant.build:
            print('Fake PrInk')


class WangProber(BaseProber):
    def __init__(self, type=HECH_PROBER):
        BaseProber.__init__(self)
        self.type = type

    def get_visa_obj(self):
        global VISA_OBJ
        global PROBER_ADDR
        global GPIB_CARDNUM
        if VISA_OBJ is None:
            VISA_OBJ = pyvisaImpl.PyvisaImpl(type='GPIB', addr=PROBER_ADDR, card=GPIB_CARDNUM)
        VISA_OBJ.set_timeout(1000)
        return VISA_OBJ

    def PrInit(self, *args):
        if not constant.build:
            print('Wang Prober PrInit:%s' % str(args))
        visa_obj = self.get_visa_obj()
        status = visa_obj.write('PrInit()')
        if status == pyvisaImpl.TIMEOUT:
            return status

        status = visa_obj.read()
        if not constant.build:
            print('Prinit visa read:', status)
        if status != 'true':
            return PrInitFail

        # every time call PrInit, go to home position(0,0)
        status = self.PrMove(0, 0)
        if status != 'true':
            return PrInitFail

        status = self.PrChuck(1)
        return status

    def PrMove(self, *args):
        if not constant.build:
            print('Wang Prober PrMove:%s' % str(args))
        visa_obj = self.get_visa_obj()
        status = visa_obj.write('PrMove(%s,%s)' % (args[0], args[1]))
        if status == pyvisaImpl.TIMEOUT:
            return status
        #
        #        status=visa_obj.wait_for_srq()
        #        if status==pyvisaImpl.TIMEOUT:
        #            return status
        #        print('wait_for_srq return:',status)
        t1 = time.time()
        status = visa_obj.read()  # read is blocked read function!
        if not constant.build:
            print('PrMove visa read:', status, 'cost time:', time.time() - t1)
        if status == 'true':
            return NO_ERR
        else:
            return PrMoveFail

    def PrChuck(self, *args):
        if not constant.build:
            print('Wang Prober  PrChuck:%s' % str(args))
            return NO_ERR

        visa_obj = self.get_visa_obj()
        status = visa_obj.write('PrChuck(%s)' % (args[0]))
        if status == pyvisaImpl.TIMEOUT:
            return status

        status = visa_obj.read()
        if not constant.build:
            print('Prchuck visa read:', status)
        if status == 'true':
            return NO_ERR
        else:
            return PrChuckFail

    # INKING function

    def PrInk(self, *args):
        if not constant.build:
            print('Wang Prober  PrInk')

        visa_obj = self.get_visa_obj()
        status = visa_obj.write('PrInk()')
        if status == pyvisaImpl.TIMEOUT:
            return status

        status = visa_obj.read()
        #        print('visa read:',status)
        if status == 'true':
            return NO_ERR
        else:
            return PrInkFail

#
###
# wp=WangProber()
# print(wp.PrInit())
# while(1):
#    print(wp.PrMove(1080,0))
#    print(wp.PrChuck(1))
#    print(wp.PrChuck(0))
#    time.sleep(0.1)
